﻿namespace Server
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    using ServerApp;
    using ServerApp.AdditionalClasses.External;

    [ServiceContract]
    public interface IAppService
    {
        #region Categories

        /// <summary>
        /// Запрос количества страниц товаров в категории
        /// </summary>
        /// <param name="categoryId">Id категории</param>
        /// <returns>int?</returns>
        [OperationContract]
        int? GetCountOfCategoryPages(int categoryId, int productOnPage);

        /// <summary>
        /// Запрос списка категорий товара
        /// </summary>
        /// <param name="language">Код языка (3 символа, http://ru.wikipedia.org/wiki/Коды_языков )</param>
        /// <param name="parentId">Id родительской категоии (Если корень = null)</param>
        /// <returns>List<CategoryView></returns>
        [OperationContract]
        List<CategoryView> GetCategories(string language, int? parentId = null);

        /// <summary>
        /// Запрос списка категорий товара, которые есть у конкретного поставщика
        /// </summary>
        /// <param name="language">Код языка (3 символа, http://ru.wikipedia.org/wiki/Коды_языков )</param>
        /// <param name="parentId">Id родительской категоии (Если корень = null)</param>
        /// <param name="producerId">Id of producer</param>
        /// <returns>List<CategoryView></returns>
        [OperationContract]
        List<CategoryView> GetCategoriesOfProducer(string language, int producerId, int? parentId = null);

        //GetCategoriesOfProducer(int? productParentCategoryId, string currentLanguage, int producerId)

        /// <summary>
        /// Загрузка полных данных по категории
        /// </summary>
        /// <param name="productCategoryId">Identifaier of product category</param>
        /// <param name="currentLanguage">Lenguage in witch category will be</param>
        /// <returns>CategoryView</returns>
        [OperationContract]
        CategoryView GetCtegoryById(int productCategoryId, string currentLanguage);

        /// <summary>
        /// Get category by identifier
        /// </summary>
        /// <param name="productParentCategoryId">Category identifier</param>
        /// <param name="currentLanguage">Current lenguage of sesion</param>
        /// <returns>Category with all information</returns>
        [OperationContract]
        CategoryAll GetCategoryAllById(int productCategoryId);

        /// <summary>
        /// Delete category by it identifier
        /// </summary>
        /// <param name="productCategoryId">Identifaier of product category</param>
        /// <returns>bool</returns>
        [OperationContract]
        bool DeleteCtegory(int productCategoryId);

        /// <summary>
        ///  Update category with description, using select language
        /// </summary>
        /// <param name="categoryAll">Category with all information</param>
        /// <returns>Category with all information</returns>
        [OperationContract]
        CategoryAll UpdateCtegory(CategoryAll categoryAll);

        /// <summary>
        /// Add category with description, using select language
        /// </summary>
        /// <param name="categoryAll">Category with all information</param>
        /// <returns>Category with all information</returns>
        [OperationContract]
        CategoryAll AddCtegory(CategoryAll categoryAll);
          
        #endregion END Categories

        #region Products

        /// <summary>
        /// Get sorted product list by category identifier on selected page
        /// </summary>
        /// <param name="productCategoryId">Category identifier</param>
        /// <param name="currentLanguage">Current lenguage of sesion</param>
        /// <param name="productSort">Sort parametr</param>
        /// <param name="page">Page number</param>
        /// <param name="countOnPage">Count products on page</param>
        /// <param name="productSort">Filters - Filter name = Filter args</param>
        /// <returns>List<ProductView></returns>
        [OperationContract]
        List<ProductView> GetProductsOnPage(int productCategoryId, string currentLanguage, ProductSort productSort, int page, int countOnPage, Dictionary<ProductFilter, object> filters = null);

        /// <summary>
        /// Get full product description by it identifier
        /// </summary>
        /// <param name="productId">Product identifierr</param>
        /// <param name="currentLanguage">>Current lenguage of sesion</param>
        /// <returns>Full information of product on selected language</returns>
        [OperationContract]
        ProductFull GetProductFullById(long productId, string currentLanguage);

        /// <summary>
        /// Delete product 
        /// </summary>
        /// <param name="productCategoryId">Product  identifier</param>
        /// <returns>If operation is successful return true,elese - false</returns>
        bool DeleteProduct(long productId);
       
        /// <summary>
        /// Adds a range of products
        /// </summary>
        /// <param name="productAll">Product with the all information about</param>
        /// <returns>Product with the all information about</returns>
        [OperationContract]
        ProductAll AddProduct(ProductAll productAll);
        
        /// <summary>
        /// Update a range of products
        /// </summary>
        /// <param name="productAll">Product with the all information about</param>
        /// <returns>Product with the all information about</returns>
        [OperationContract]
        ProductAll UpdateProduct(ProductAll productAll);

        /// <summary>
        /// Adds a range of products
        /// </summary>
        /// <param name="productId">Identificator of product</param>
        /// <returns>Product with the all information about</returns>
        [OperationContract]
        ProductAll GetProductAllById(long productAllId);

        [OperationContract]
        List<ProductView> GetAllProductsOfProducer(int producerId, string currentLanguage);

        #endregion END Products

        #region Product Item
        /// <summary>
        /// Update product item in base
        /// </summary>
        /// <param name="productItemModel">Changed product item</param>
        /// <returns>Product item</returns>
        [OperationContract]
        ProductItemModel GetProductItemById(long productItemId);
       
        /// <summary>
        /// Add product item in base
        /// </summary>
        /// <param name="productItemModel">Changed product item</param>
        /// <returns>Product item</returns>
        [OperationContract]
        ProductItemModel AddProductItem(ProductItemModel productItemModel);
       
        /// <summary>
        /// Update product item in base
        /// </summary>
        /// <param name="productItemModel">Changed product item</param>
        /// <returns>Product item</returns>
        [OperationContract]
        ProductItemModel UpdateProductItem(ProductItemModel productItemModel);

        /// <summary>
        /// Delete product item from base
        /// </summary>
        /// <param name="productItemId">Product item identifier</param>
        /// <returns>If operation is successful return true,elese - false</returns>
        [OperationContract]
        bool DeleteProductItem(long productItemId);

        #endregion END 

        #region Places

        /// <summary>
        /// Get All Places
        /// </summary>
        /// <param name="language">Current language</param>
        /// <returns>List if places</returns>
        [OperationContract]
        List<PlaceView> GetPlaces(string language);

        /// <summary>
        /// Get place
        /// </summary>
        /// <param name="placeAll">Full place information with list of localizations</param>
        /// <returns>Full place information with list of localizations</returns>
        [OperationContract]
        PlaceAll GetPlaceAll(int placeAllId);

        /// <summary>
        /// Gets places by its name
        /// </summary>
        /// <param name="placeName">Name of the place</param>
        /// <returns>placeAll value</returns>
        [OperationContract]
        PlaceAll GetPlaceAllByName(string placeName);

        /// <summary>
        /// Add place in base
        /// </summary>
        /// <param name="placeAll">Full place information with list of localizations</param>
        /// <returns>Full place information with list of localizations</returns>
        [OperationContract]
        PlaceAll AddPlace(PlaceAll placeAll);
     
        /// <summary>
        /// Update place
        /// </summary>
        /// <param name="placeAll">Full place information with list of localizations</param>
        /// <returns>Full place information with list of localizations</returns>
        [OperationContract]
        PlaceAll UpdatePlace(PlaceAll placeAll);
    
        /// <summary>
        /// Delete place from base
        /// </summary>
        /// <param name="placeId">Place identifaier</param>
        /// <returns>If operation is successful return true,elese - falentity</returns>
        [OperationContract]
        bool DeletePlace(int placeId);

        /// <summary>
        /// For transmitting the entity PlaceLocalizationModel
        /// </summary>
        [OperationContract]
        PlaceLocalizationModel GetPlaceLocalizationModelTest();
               
        #endregion END Places

        #region Orders

        /// <summary>
        /// Sends order (used by customer or manager) 
        /// </summary>
        /// <param name="custumerId">Id of the customer</param>
        /// <param name="products">Dictionary of the products [productId - count]</param>
        /// <param name="placeId">Id place of the order destination</param>
        /// <param name="whoProcessId">Id of the ecxecutor. If 0 - order is free</param>
        /// <returns>new object of OrderFull</returns>
        [OperationContract]
        OrderFull SetOrder(long? custumerId, Dictionary<long, int> products, int placeId, long? whoProcessId = 0);

        /// <summary>
        /// Gets the history of the orders of the one customer
        /// </summary>
        /// <param name="custumerId">customer id</param>
        /// <param name="count">count of the orders for review</param>
        /// <returns>list of the OrderView objects</returns>
        [OperationContract]
        List<OrderView> GetOrderHistory(long custumerId, int count);

        /// <summary>
        /// Gets the list of the orders views
        /// </summary>        
        /// <param name="page">Number of the page</param>        
        /// <param name="filter">Dictionary<OrderFilter.value,object></param>
        /// <param name="numberOnThePage">Number of the orders on the one page</param>
        /// <returns>list of the orderView</returns>        
        [OperationContract]
        List<OrderView> GetOrderList(Dictionary<OrderFilter, object> filter, int page, int numberOnThePage);

        /// <summary>
        /// Gets the order by its id
        /// </summary>
        /// <param name="orderId">Id of the order</param>
        /// <param name="language">Language of the text</param>
        /// <returns>OrderFull value</returns>
        [OperationContract]
        OrderFull GetOrder(long orderId, string language);

        /// <summary>
        /// Reserves the order
        /// </summary>
        /// <param name="orderId">order id</param>
        /// <param name="executorId">executor Id</param>
        /// <returns>updated OrderFull value</returns>
        [OperationContract]
        OrderFull ReserveOrder(long orderId, long executorId);

        /// <summary>
        /// Reserves products for the order
        /// </summary>
        /// <param name="orderId">Id of the order</param>
        /// <param name="productId">Id of the product</param>
        /// <param name="count">number of the products</param>
        /// <returns>difference between number of the order products and real products</returns>
        [OperationContract]
        int ReserveProduct(long orderId, long productId, int count);

        /// <summary>
        /// Updates the order
        /// </summary>
        /// <param name="newOrder">OrderFull value of the order</param>
        /// <returns>OrderFull value of the updated order</returns>
        [OperationContract]
        OrderFull UpdateOrder(OrderFull newOrder);        

        /// <summary>
        /// Closes the order by its id
        /// </summary>
        /// <param name="orderId">order id</param>
        /// <returns>updated orderFull value</returns>
        [OperationContract]
        OrderFull CloseOrder(long orderId);

        /// <summary>
        /// Cancel the order and unreserves all products of this order
        /// </summary>
        /// <param name="orderId">Id of the order</param>
        /// <returns>bool value</returns>
        [OperationContract]
        bool CancelOrder(long orderId);

        /// <summary>
        /// Add a new product to the order
        /// </summary>
        /// <param name="orderId">Id of the order</param>
        /// <param name="productId">Id of the product</param>
        /// <param name="count">Number of the products</param>
        /// <returns>new OrderFUll value of the current order</returns>
        [OperationContract]
        OrderFull AddProductToOrder(long orderId, long productId, int count);

        /// <summary>
        /// Delete a product from the current order
        /// </summary>
        /// <param name="orderId">Id of the order</param>
        /// <param name="productId">Id of the product</param>
        /// <param name="count">Number of the products</param>
        /// <returns>new OrderFUll value of the current order</returns>
        [OperationContract]
        OrderFull DeleteProductFromOrder(long orderId, long productId, int count);
        #endregion

        #region User managment

        /// <summary>
        /// Логин
        /// </summary>
        /// <param name="login">Логин</param>
        /// <param name="password">Пароль</param>
        /// <param name="placeId">Id места работы, null для web-магазина</param>
        /// <returns>User</returns>
        [OperationContract]
        User Login(string login, string password, int? placeId);

        /// <summary>
        /// Get user data by id
        /// </summary>
        /// <param name="id">user Id</param>
        /// <returns>User</returns>
        [OperationContract]
        User GetUser(long id);

        /// <summary>
        /// Регистрация/обновление данных пользователя
        /// </summary>
        /// <param name="user">Данные пользователя</param>
        /// <returns>User</returns>
        [OperationContract]
        User SetUser(User user);

        /// <summary>
        /// Удаление пользователя
        /// </summary>
        /// <param name="user">Данные пользователя</param>
        /// <returns>User</returns>
        [OperationContract]
        bool DeleteUser(User user);

        [OperationContract]
        Dictionary<long, User> GetUserList(Dictionary<string, object> filter, int page = 0);

        #endregion END User managment

        #region Producers

        /// <summary>
        /// Add Producer
        /// </summary>
        /// <param name="producer">Concrete poducer</param>
        /// <returns>1 - added successfuly, 0 - fail</returns>
        [OperationContract]
        int AddProducer(ExternalProducerView externalProducer, List<long> productList);

        /// <summary>
        /// Update producer
        /// </summary>
        /// <param name="producer">Concrete producer</param>
        /// <returns>1 - updated successfuly, 0 - fail</returns>
        [OperationContract]
        int UpdateProducer(Producer producer);

        /// <summary>
        /// Delete producer
        /// </summary>
        /// <param name="producer">Concrete producer</param>
        /// <returns>User</returns>
        [OperationContract]
        int DeleteProducer(Producer producer);

        /// <summary>
        /// Get all the external producers
        /// </summary>
        /// <returns>list of external producers</returns>
        [OperationContract]
        List<ExternalProducerView> GetProducers();

        #endregion Producers

        [OperationContract]
        void Test();

    }
}
